﻿using HomeCloudStorageSystem.DataBase;
using HomeCloudStorageSystem.Helps;
using HomeCloudStorageSystem.Models;
using Microsoft.AspNetCore.Server.IIS.Core;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.IO;
using System.Xml.Linq;

namespace HomeCloudStorageSystem.Services
{
    public class FileInfosRepository : IFileInfosRepository
    {
        private readonly AppDbContext _context;
        public FileInfosRepository(AppDbContext appDbContext)
        {
            _context = appDbContext;
        }
        public IEnumerable<FileInfos> GetFileInfos(string? keyword)
        {
            if (keyword != null)
            {
                keyword = keyword.Trim();
                return _context.FileInfo.Where(n => n.FileName.Contains(keyword)
                || n.ExtName.Contains(keyword)
                ).ToList();
            }
            return _context.FileInfo;
        }
        public FileInfos GetFileInfosById(int id)
        {
            return _context.FileInfo.Where(n => n.Id == id).FirstOrDefault();
        }
        public byte[] GetFileById(string path)
        {
            //读取文件为字节流
            byte[] fileBytes = File.ReadAllBytes(path);
            return fileBytes;
        }
        public IEnumerable<FileInfos> GetFileInfosByDirectory(int directoryId)
        {
            return _context.FileInfo.Where(n => n.DirectoryId == directoryId).ToList();
        }
        public void AddFileInfos(IEnumerable<IFormFile> files, int creator, string? describe, int? fileDirectoryId,out Dictionary<string, string> addFileMessage)
        {
            Dictionary<string, string> resultMessages = new Dictionary<string, string>();
            try
            {
                // 添加文件上传记录日志
                var fileUploagLogToSQL = new FileUploagLog
                {
                    UploadPersonnel = creator,
                    OperationTime = DateTime.Now.ToString("yyyy-MM-dd"),
                    Describe = describe == null? "": describe,
                    State = "保存成功"
                };
                _context.FileUploagLog.Add(fileUploagLogToSQL);
                _context.SaveChanges();
            }
            catch
            {
                resultMessages.Add("AllFile", "上传失败");
                addFileMessage = resultMessages;
                return;
            }
            string filePath = null;
            List<IFormFile> filesToDb = new List<IFormFile>();
            foreach (var file in files)
            {
                string fileName = file.FileName;
                if (file == null || file.Length <= 0)
                {
                    resultMessages.Add(fileName, "文件不为空");
                    continue;
                }
                if (fileDirectoryId != null && fileDirectoryId > 0)
                {
                    var fileDirectory = _context.FileDirectory.Where(n => n.Id == fileDirectoryId).FirstOrDefault();
                    var directoryPath = fileDirectory.DirectoryPath;
                    var directoryName = fileDirectory.DirectoryName;
                    filePath = Path.Combine(directoryPath + directoryName + "/");
                }
                else
                {
                    filePath = @"../../家庭云盘系统文件夹/上传文件/";
                }
                string fullPath = Path.Combine(filePath, fileName);
                if (File.Exists(fullPath))
                {
                    if (resultMessages.ContainsKey(fileName))
                    {
                        resultMessages[fileName] = resultMessages[fileName] + "，但存在文件重复上传";
                    }
                    else
                    {
                        resultMessages.Add(fileName, "文件已存在");
                    }
                    continue;
                }
                //保存文件
                byte[] fileByte = ReadStreamHelp.ReadStream(file.OpenReadStream());
                using (var fileStream = new FileStream(fullPath, FileMode.CreateNew))
                {
                    fileStream.Write(fileByte, 0, fileByte.Length);
                }
                resultMessages.Add(fileName, "上传成功");
                filesToDb.Add(file);
            }

            // 获取 FileUploagLog表中最新的一条数据
            var id = _context.FileUploagLog.ToList();
            int fileUploagLogId = id.Max(n => n.Id);
            var fileUploagLog = _context.FileUploagLog.Where(n => n.Id == fileUploagLogId).FirstOrDefault();
            foreach (var file in filesToDb)
            {
                //创建事务
                // 事务回退的是数据库，还需要对文件进行删除操作
                var transaction = _context.Database.BeginTransaction();
                try
                {
                    //添加文件信息到数据库中
                    var fileInfo = new FileInfos
                    {
                        FileName = Path.GetFileName(file.FileName),
                        ExtName = Path.GetExtension(file.FileName),
                        FileUploagLogId = fileUploagLog.Id,
                        FilePath = filePath + file.FileName,
                        DirectoryId = fileDirectoryId <=0 || fileDirectoryId ==null? 0 : (int)fileDirectoryId,
                        UploadTime = DateTime.Now.ToString("yyyy-MM-dd"),
                        Uploader = creator,
                    };
                    _context.FileInfo.Add(fileInfo);
                    _context.SaveChanges();
                    transaction.Commit();
                    transaction.Dispose();
                }
                catch
                {
                    File.Delete(filePath + file.FileName);
                    transaction.Rollback();
                    resultMessages[file.FileName] = "上传失败";
                }
            }
            if (filesToDb.Count <= 0)
            {
                //如果所有文件都上传失败，则删除 fileUploagLog
                _context.Remove(fileUploagLog);
                _context.SaveChanges();
            }
            addFileMessage = resultMessages;
        }
        public void RemoveFileInfo(FileInfos fileInfo)
        {
            var transaction = _context.Database.BeginTransaction();
            //复制一份文件
            string name = fileInfo.FilePath;
            var testFile = fileInfo.FilePath + ".test";
            File.Copy(fileInfo.FilePath, testFile);
            try
            {
                _context.Remove(fileInfo);
                _context.SaveChanges();
                File.Delete(fileInfo.FilePath);
                transaction.Commit();
            }
            catch
            {
                File.Copy(testFile, name);
                transaction.Rollback();
            }
            finally
            {
                File.Delete(testFile);
            }
        }
        public bool Save()
        {
            return (_context.SaveChanges() > 0);
        }
    }
}
